#ifndef __SM2_HEADER__
#define __SM2_HEADER__

# ifdef __cplusplus
extern "C"{
#endif

/**
 * @brief   根据用ID及公钥，求用于签名或验签的预处理结果
 *
 * @param   userid          [in]    用户ID
 * @param   userid_len      [in]    userid的字节数
 * @param   publickey[64]   [in]    公钥数据（x|y串联）
 * @param   msg             [in]    要签名的消息
 * @param   msg_len         [in]    msg的字节数
 * @param   e[32]           [out]   32字节，用于签名或验签
 *
 * @return  0表示成功，-1表示内存不足
 */
int sm3_e(unsigned char *userid, int userid_len, unsigned char publickey[64], unsigned char *msg, int msg_len, unsigned char e[32]);

/**
 * @brief   生成SM2密钥对
 *
 * @param   publickey[64]   [out]   公钥数据（x|y串联）
 * @param   privkey[32]     [out]   私钥数据
 */
void sm2_keygen(unsigned char publickey[64], unsigned char privkey[32]);

/**
 * @brief   SM2算法签名运算
 *
 * @param   hash[32]        [in]    预处理结果（sm3_e()的输出）
 * @param   privkey[32]     [in]    私钥数据
 * @param   signature[64]   [out]   签名值结果（r|s串联）
 */
void sm2_sign(unsigned char hash[32], unsigned char privkey[32], unsigned char signature[64]);

/**
 * @brief   SM2算法签名运算，函数内进行预处理
 *
 * @param   indata              [in]    待签名消息数据
 * @param   inlen               [in]    indata的字节数
 * @param   publickey[64]       [in]    公钥数据（x|y串联）
 * @param   privatekey[32]      [in]    私钥数据
 * @param   signature[64]       [out]   签名结果（r|s串联）
 */
void Sign_SM2WithSM3(unsigned char * indata, int inlen, unsigned char publickey[64], unsigned char privatekey[32], unsigned char signature[64]);

/**
 * @brief   SM2算法验证签名运算
 *
 * @param   hash[32]        [in]    预处理结果（sm3_e()的输出）
 * @param   signature[64]   [in]    签名值（r|s串联）
 * @param   publickey[64]   [in]    公钥数据（x|y串联
 *
 * @return  通过返回1，失败返回0
 */
int sm2_verify(unsigned char hash[32], unsigned char signature[64], unsigned char publickey[64]);

/**
 * @brief   SM2算法验证签名运算，函数内进行预处理
 *
 * @param   indata              [in]    签名的原文数据
 * @param   inlen               [in]    indata的字节数
 * @param   signature[64]       [in]    签名值（r|s串联）
 * @param   publickey[64]       [in]    公钥数据（x|y串联
 *
 * @return  通过返回1，失败返回0
 */
int Verify_SM2WithSM3(unsigned char * indata, int inlen, unsigned char signature[64], unsigned char publickey[64]);

/**
 * @brief   用SM2公钥加密数据（加密结果比输入数据多96字节）
 *
 * @param   msg             [in]    要加密的数据
 * @param   msglen          [in]    msg的字节数
 * @param   publickey[32]   [in]    公钥数据（x|y串联）
 * @param   wxlen           [in]    wx的字节数
 * @param   wy              [in]    公钥的y坐标值
 
 * @param   outmsg          [out]   加密结果（比输入数据多96字节），[ C1 || C3 || C2 ]
 *
 * @return  加密成功返回outmsg的长度（msglen+96），失败返回-1
 */
int sm2_encrypt(unsigned char *msg,int msglen, unsigned char publickey[64], unsigned char *outmsg);

/**
 * @brief   用SM2私钥解密数据（解密结果比输入数据少96字节）
 *
 * @param   msg             [in]    要解密的数据，[ C1 || C3 || C2 ]
 * @param   msglen          [in]    msg的字节数
 * @param   privkey[32]     [in]    私钥值
 * @param   outmsg          [out]   解密结果（比输入少96字节）   
 *
 * @return  加密成功返回outmsg的长度（msglen-96），失败返回-1
 */
int sm2_decrypt(unsigned char *msg,int msglen, unsigned char privkey[32], unsigned char *outmsg);

# ifdef __cplusplus
}
#endif

#endif
